

#include "frame_operate.h"
#include <bits/types/FILE.h>
#include <cstddef>
#include <cstdio>
#include <libavutil/frame.h>

extern "C" {

    #include <libavutil/samplefmt.h>
    #include <libavutil/pixfmt.h>
    #include <libavutil/pixdesc.h>
}

int WriteAudioData(AVFrame *frame, FILE * file_handle) {

    // 多少位的编码 
    int data_size = av_get_bytes_per_sample((AVSampleFormat)frame->format);
    if (data_size < 0) {

        return -1;
    }
    // frame->data 中的音频数据是以packet形式放置的,在原始pcm数据中是以planer放置的
    for (int index = 0; index < frame->nb_samples; index++) {

        for (int ch = 0; ch < frame->channels; ch++) {

            // null at last parameter
            fwrite(frame->data[ch] + data_size * index, 1, data_size, file_handle);
        }
    }
    return 0;
}

int WriteVideoData(AVFrame *frame, FILE * file_handle) {

    // yuv420
    std::string video_format_name = av_get_pix_fmt_name((AVPixelFormat)frame->format);
    if (video_format_name.compare("yuv420p") == 0) {

        hnhj::ProcessYUV420(frame, file_handle);
    } 
    return 0;
}


int hnhj::ProcessYUV420(AVFrame * frame, FILE * file_handle) {

    // 4:1:1
    for (int index = 0; index < 3; index++) {

        int width  = index == 0 ? frame->width  : frame->width/2;
        int height = index == 0 ? frame->height : frame->height/2;
        
        for (int height_index = 0; height_index < height; height_index++) {

            // use NULL
            fwrite(frame->data[index], 1, width, file_handle);
            frame->data[index] += frame->linesize[index];
        }
    }
    return 0;
} 

int hnhj::ProcessYUV422(AVFrame * frame, FILE * file_handle) {

    // 4:2:2
    // for (int index = 0; index < )
    return 0;
}

int hnhj::ProcessYUY444(AVFrame * frame, FILE * file_handle) {


    for (int index = 0; index < 3; index++) {

        fwrite(frame->data[index], 1, frame->width, file_handle);
        frame->data[index] += frame->linesize[index];
    }
    return 0;
}

int hnhj::ProcessPCMData(AVFrame *frame) {

    int sample_byte = av_get_bytes_per_sample((AVSampleFormat)frame->format);

    for (int index = 0; index < frame->nb_samples; index++) {

        for (int index_channel = 0; index_channel < frame->channels; index_channel++) {

            fwrite(frame->data[index_channel] + index * sample_byte, 1, sample_byte, NULL);
        }
    }
    return 0;
}

